package com.tul.exercise.base.java8.interfaceDemo;

import com.tul.exercise.base.java8.stream.base.Apple;
import com.tul.exercise.base.utils.MathUtils;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

/**
 * @author tuliang
 */
public class InterfaceTest {

    @Test
    @DisplayName("比较器复合")
    public void test01() {
        List<Apple> apples = Apple.createApples(20);
        apples.forEach(System.out::println);

        System.out.println("\n\n");

        apples.sort(Comparator.comparing(Apple::getWeight)
                .reversed()
                .thenComparing(Apple::getColor)
                .thenComparing(Apple::getName));
        apples.forEach(System.out::println);
    }

    @Test
    @DisplayName("谓词复合")
    public void test02() {
        List<Apple> apples = Apple.createApples(100);

        // 红色苹果
        Predicate<Apple> redApple = (Apple a) -> a.getColor().equals("red");
        List<Apple> redAppleList = apples.stream().filter(redApple).collect(Collectors.toList());
        System.out.println(redAppleList.size());


        // 重的苹果
        Predicate<Apple> heavyApple = (Apple a) -> a.getWeight() > 200;
        List<Apple> heavyAppleList = apples.stream().filter(heavyApple).collect(Collectors.toList());
        System.out.println(heavyAppleList.size());

        // 红色且重的苹果
        Predicate<Apple> redAndHeavyApple = redApple.and(heavyApple);
        List<Apple> redAndHeavyApples = apples.stream().filter(redAndHeavyApple)
                .collect(Collectors.toList());
        System.out.println(redAndHeavyApples.size());
    }

    @Test
    @DisplayName("函数复合")
    public void test03() {
        Function<Double, Double> sin = x -> Math.sin(x);
        Function<Double, Double> cos = x -> Math.cos(x);
        Function<Double, Double> f = x -> x * 2 + 4;

        // g = sin(f(x))
        Function<Double, Double> g = sin.andThen(f);

        LongStream.range(1, 1000).forEach(n ->
                System.out.println(g.apply(Double.valueOf(n)))
        );
    }
}
